<?php
class server
{
    private $serv;
    
    public function __construct(){
        $this->serv = new swoole_websocket_server("0.0.0.0", 9503);
        $this->serv->set([
            'worker_num' => 2,
            'dispatch_mode' => 1,
        ]);
        $this->serv->on('WorkerStart', array($this, 'onWorkerStart'));
        $this->serv->on('Request',  array($this, 'onRequest'));
        $this->serv->on('Open',     array($this, 'onOpen'));
        $this->serv->on('Message',  array($this, 'onMessage'));
        $this->serv->on('Close',    array($this, 'onClose'));
        $this->serv->start();
    }
    
    public function onWorkerStart(swoole_websocket_server $serv)
    {
        $serv->redis = new Redis();
        $serv->redis->connect('127.0.0.1', 6379);
        
        $serv->db = new swoole_mysql;
        $serv->db->config = [
            'host' => '127.0.0.1',
            'port' => 3306,
            'user' => 'tool',
            'password' => 'toolb8h5zr2hj0',
            'database' => 'tool',
            'chatset'  => 'utf8' //指定字符集
        ];
        $serv->db->connect($serv->db->config, function($db, $r) {});
        
        //mysql心跳
        swoole_timer_tick(2000 * 60 * 60, function(){
            $serv->db->query("select 1 limit 1", function($db, $r){echo "mysql ping\n";});
        });
    }

    public function onRequest(swoole_http_request $request, swoole_http_response $response)
    {
    }
    
    public function onOpen(swoole_websocket_server $serv, swoole_http_request $request)
    {
        $sign = md5($request->header['origin']);
        $serv->redis->set("barrage:sign:{$request->fd}", $sign);
        $serv->redis->sadd("barrage:group:{$sign}", $request->fd);
    }

    public function onMessage(swoole_websocket_server $serv, swoole_websocket_frame $frame)
    {
        foreach ($this->getMembersBySign($this->getSignByFd($frame->fd)) as $fd){
            $serv->push($fd,$frame->data);
        }
    }
    
    public function onClose(swoole_websocket_server $serv, $fd)
    {
        print_R('srem barrage:group:'.($this->getSignByFd($fd)).$fd);
        $serv->redis->srem('barrage:group:'.($this->getSignByFd($fd)), $fd);
        $serv->redis->del("barrage:sign:{$fd}");
    }
    
    /**
     * getSignByFd
     * @param  int $fd
     * @return string 
     */
    public function getSignByFd($fd) : string
    {
        return $this->serv->redis->get("barrage:sign:{$fd}");
    }
    
    /**
     * getMembersBySign
     * @param  string $sign
     * @return string 
     */
    public function getMembersBySign($sign) : array
    {
       return $this->serv->redis->smembers("barrage:group:{$sign}");
    }
}
new server();
